# language: JSVM2

/**
 * @fileoverview com.homolo.commons.util.DateFormat class {@link http://jsvm.org/}
 * @file		DateFormat.jsc
 * @author	Wan Changhua
 * @version	2.01, 10/23/05
 * @since		JSVM2.02
 */

package com.homolo.commons.util;

import js.lang.NotSupportException;
import js.lang.ArgumentException;

import com.homolo.commons.util.StringUtils;
import com.homolo.commons.util.TypeUtils;

/**
 * Inherit from JObject
 * @author	Wan Changhua
 * @version	2.01, 10/23/05
 * @extends js.lang.JObject
 * @class DateFormat is a utility class for date
 * @constructor
 * @final
 */

class DateFormat (pattern)
{
	if (TypeUtils.isNull(pattern))
	{
		this.__pattern = "yyyy-MM-dd HH:mm:ss";
	}
	else
	{
		this.__pattern = pattern
			.replace(/y{4,999}/g, "yyyy")
			.replace(/M{2,999}/g, "MM")
			.replace(/d{2,999}/g, "dd")
			.replace(/H{2,999}/g, "HH")
			.replace(/m{2,999}/g, "mm")
			.replace(/s{2,999}/g, "ss")
			.replace(/S{3,999}/g, "SSS")
			.replace(/S+/g, "S")
			.replace(/E+/g, "E")
			.replace(/G+/g, "G");
	}

	this.__regexp = new RegExp(
		this.__pattern
			.replace(/([^yMdHmsS])/g, "\\$1")
			.replace(/d{2}/g, "(\\d{2})")
			.replace(/(^|[^\\])d/g, "$1(\\d{1,2})")
			.replace(/y{4}/g, "(\\d{4})")
			.replace(/y{2}/g, "(\\d{2})")
			.replace(/M{2}/g, "(\\d{2})")
			.replace(/M/g, "(\\d{1,2})")
			.replace(/H{2}/g, "(\\d{2})")
			.replace(/H/g, "(\\d{1,2})")
			.replace(/m{2}/g, "(\\d{2})")
			.replace(/m/g, "(\\d{1,2})")
			.replace(/s{2}/g, "(\\d{2})")
			.replace(/s/g, "(\\d{1,2})")
			.replace(/S{3}/g, "(\\d{3})")
			.replace(/S/g, "(\\d{1,3})")
			.replace(/S+/g, "S"));
	
	this.__patternFlags = [];

	if (new RegExp(
		this.__pattern
			.replace(/([^yMdHmsS])/g, "\\$1")
			.replace(/d{2}/g, "(\\w{2})")
			.replace(/d/g, "(\\w{1,2})")
			.replace(/y{4}/g, "(\\w{4})")
			.replace(/y{2}/g, "(\\w{2})")
			.replace(/M{2}/g, "(\\w{2})")
			.replace(/M/g, "(\\w{1,2})")
			.replace(/H{2}/g, "(\\w{2})")
			.replace(/H/g, "(\\w{1,2})")
			.replace(/m{2}/g, "(\\w{2})")
			.replace(/m/g, "(\\w{1,2})")
			.replace(/s{2}/g, "(\\w{2})")
			.replace(/s/g, "(\\w{1,2})")
			.replace(/S{3}/g, "(\\w{3})")
			.replace(/S/g, "(\\w{1,3})")
			.replace(/S+/g, "S")).test(this.__pattern))
		{
			var i = 1;
			var v = RegExp.$1;
			while (v != "")
			{
				this.__patternFlags[i - 1] = v;
				eval("v=RegExp.$" + (++i));
			}
		}
}

var defaultInstance = null;

DateFormat.getInstance = function ()
{
	if (defaultInstance == null)
	{
		defaultInstance = new DateFormat();
	}
	return defaultInstance;
}

/**
 * format a date object to string
 * @param d the input date
 * @return String
 */
DateFormat.prototype.format = function (d)
{
	if (d == null)
	{
		return null;
	}
	var year = String(d.getFullYear());
	var month = d.getMonth() + 1;
	var day = d.getDate();
	var hours = d.getHours();
	var minutes = d.getMinutes();
	var seconds = d.getSeconds();
	var ms = d.getMilliseconds();
	var dayOfWeek = d.getDay();

	return this.__pattern
		.replace(/yyyy/g, year)
		.replace(/y+/g, StringUtils.right(year, 2))
		.replace(/MM/g, StringUtils.fixLength(month, 2))
		.replace(/M/g, String(month))
		.replace(/dd/g, StringUtils.fixLength(day, 2))
		.replace(/d/g, String(day))
		.replace(/HH/g, StringUtils.fixLength(hours, 2))
		.replace(/H/g, String(hours))
		.replace(/mm/g, StringUtils.fixLength(minutes, 2))
		.replace(/m/g, String(minutes))
		.replace(/ss/g, StringUtils.fixLength(seconds, 2))
		.replace(/s/g, String(seconds))
		.replace(/SSS/g, StringUtils.fixLength(ms, 3))
		.replace(/S/g, String(ms))
		.replace(/E/g, String(dayOfWeek))
		.replace(/G/g, "公元");

}



/**
 * parse a string object to date object
 * @param d the input string
 * @return Date
 */
DateFormat.prototype.parse = function (source)
{
	if(!this.__regexp.test(source))
	{
		throw new ArgumentException(this.getClass().getName()
			+ ".parse() argument error: " +  source);
	}
	var date = new Date();
	for (var i = 0; i < this.__patternFlags.length; i++)
	{
		var val = eval("RegExp.$" + (i + 1));
		if (val == "")
		{
			break;
		}
		else if (isNaN(val))
		{
			continue;
		}
		else
		{
			val = parseInt(val, 10);
		}
		switch (this.__patternFlags[i])
		{
			case "yyyy" : date.setYear(val); break;
			case "yyyy" : date.setYear(2000 + val); break;
			case "M" : 
			case "MM" : date.setMonth(val - 1); break;
			case "dd" : 
			case "d" : date.setDate(val); break;
			case "HH" : 
			case "H" : date.setHours(val); break;
			case "mm" : 
			case "m" : date.setMinutes(val); break;
			case "ss" : 
			case "s" : date.setSeconds(val); break;
			case "SSS" : 
			case "S" : date.setMilliseconds(val); break;
			default : break;
		}		
	}
	return date;
}


var  PATTERN_YEAR = "y";
var  PATTERN_NONTH = "M";
// var  PATTERN_INYEAR_DAY = "D";
var  PATTERN_INMONTH_DAY = "d";
var  PATTERN_INWEEK_DAY = "E";

// var  PATTERN_INYEAR_WEEK = "W";
// var  PATTERN_INMONTH_WEEK = "w";

// var  PATTERN_AMPMMARKER = "a";

var  PATTERN_INDAY_HOUR = "H";
var  PATTERN_INAMPM_HOUR = "h";
var  PATTERN_MINUTE = "m";
var  PATTERN_SECOND = "s";
var  PATTERN_MILLISECOND = "S";
var  PATTERN_ZONE = "z";
var  PATTERN_ZONE = "G";
